<template>
    <div class="container">
        <div id="mapContainer" class="TianDiMap"></div>

        <div id="popup">北京欢迎您</div>
        <div class="ol-popup" ref="olPopup">{{olPopupText}}</div>
    </div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import 'ol/ol.css';
import * as ol from 'ol';
import { Feature, Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import { XYZ } from 'ol/source';
import Overlay from 'ol/Overlay';
import { defaults, MousePosition, FullScreen, ScaleLine } from 'ol/control';
import { fromLonLat } from 'ol/proj';
import { Point, Polygon } from 'ol/geom';

import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Style, Icon, Stroke, Fill } from 'ol/style';
import {
    Translate,
    Draw,
    defaults as defaultInteractions
} from 'ol/interaction';

import iconPng from '@/assets/mouse_location_ing.png';
import iconLogo from '@/assets/logo.png';
import icon1 from '@/assets/icon1.png';
import { createBox } from 'ol/interaction/Draw';
import { Coordinate } from 'ol/coordinate';

import { Circle as sCircle } from 'ol/style';

// 地图是一层一层的加载
// ol 是以面向对象的形式来设计的api
// map中的配置选项
// target 表示地图示例挂载的容器
// view 表示地图的视图
// layers 表示地图的图层 所有的地图都有一个底图，Source 就是地图的来源

const map = ref();
const olPopup = ref(null);
const olPopupText = ref('');

const initMap = () => {
    map.value = new Map({
        target: 'mapContainer'
    });

    const layer = new TileLayer({
        source: new XYZ({
            // url: `http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}`
            // url: `http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8`
            // url: `http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8`
            // url: `http://webst0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}`
            url: `http://wprd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7`
        }),
        opacity: 0.9
    });
    map.value.addLayer(layer);

    const view = new View({
        center: [116.397477, 39.908692],
        zoom: 10,
        projection: 'EPSG:4326'
    });
    const state = view.getState();
    console.log(state, 'state=');
    map.value.setView(view);

    map.value.addControl(new FullScreen());
    map.value.addControl(new ScaleLine());

    map.value.on('moveend', (e) => {
        console.log('地图移动', e);
    });

    map.value.on('rendercomplete', () => {
        console.log('渲染完成');
    });

    map.value.on('click', (e) => {
        console.log('地图点击', e.coordinate);
    });

    overlayFunc();

    featureFunc();

    tooltipOverlay();

    drawPolygon();

    calculateExtent();

    // renderArea([
    //     [116.28509666151275, 39.91139246932324],
    //     [116.38978126363469, 39.91743515706737],
    //     [116.40316361855601, 39.862835214133085],
    //     [116.337546891431, 39.854418627459474],
    //     [116.26631819308, 39.85333957725266],
    //     [116.28509666151275, 39.91139246932324]
    // ]);

    setMarker();
};

// 将dom元素添加到地图
let overlayFunc = () => {
    let el = document.createElement('div');
    el.innerHTML = '<div style="font-size:24px;color:#f00">hello world</div>';
    let marker = new Overlay({
        element: el,
        position: fromLonLat(
            [116.92636521269637, 39.883178793806174],
            'EPSG:4326'
        ),
        offset: [-17, -17],
        autoPan: true
    });
    map.value.addOverlay(marker);

    const overlay = new Overlay({
        element: document.getElementById('popup'), // 关联的HTML元素
        position: [116.49775970006971, 39.9358512147705], // 绑定的坐标
        autoPan: true // 自动平移地图以确保可见
    });
    map.value.addOverlay(overlay);
};

// 元素交互
let featureFunc = () => {
    // 实例化要素
    let feature = new Feature({
        geometry: new Point([116.34615955501815, 39.82346268394583]) // 地理几何图形选用点几何
    });

    // 设置样式，这里就是显示一张图片icon
    feature.setStyle([
        new Style({
            image: new Icon({
                anchor: [0.5, 1],
                size: [50, 50],
                src: iconPng
            })
        })
    ]);

    // 矢量源
    let source = new VectorSource({
        features: [feature]
    });

    // 样式除了可以设置在单个feature上，也可以统一设置在矢量图层上
    let vector = new VectorLayer({
        source: source,
        style: new Style({
            image: new Icon({
                anchor: [0.5, 1],
                size: [100, 100],
                src: iconPng
            })
        })
    });

    map.value.addLayer(vector);

    // 将要素添加到拖动交互中
    let translate = new Translate({
        layers: [vector]
    });
    map.value.addInteraction(translate);
    // 可以监听一下拖动开始和结束的事件，拖动后的经纬度可以从e里面获取
    translate.on('translateend', (e) => {
        console.log('拖动结束：', e);
    });
    translate.on('translatestart', (e) => {
        console.log('拖动开始：', e);
    });
};

// Draw交互
let setMarker = () => {
    let feature = new Feature({
        geometry: new Point([115.8427625744659, 39.86944268250419])
    });
    let source = new VectorSource({
        features: [feature]
    });

    let vector = new VectorLayer({
        source: source,
        style: new Style({
            image: new Icon({
                anchor: [0.5, 1],
                size: [100, 100],
                src: iconLogo
            })
        })
    });
    map.value.addLayer(vector);

    let draw = new Draw({
        source: source,
        type: 'Point',
        style: new Style({
            image: new Icon({
                anchor: [0.5, 1],
                size: [50, 50],
                src: icon1
            })
        })
    });

    draw.on('drawend', (e) => {
        console.log('drawend=', e);
        // 如果只需要放置一个的话可以移除该交互，否则可以一直添加
        map.value.removeInteraction(draw);
    });

    map.value.addInteraction(draw);
};

// Draw绘制多边形
let drawPolygon = () => {
    let source = new VectorSource();
    let vector = new VectorLayer({
        source: source
    });
    map.value.addLayer(vector);
    let draw = new Draw({
        source: source,
        type: 'Circle', //绘制圆形
        geometryFunction: createBox() //绘制矩形
        // type: 'Polygon' //绘制多边形
    });
    map.value.addInteraction(draw);

    draw.on('drawend', (e) => {
        console.log('绘制多边形结束：', e);
    });
};

// Draw根据经纬度坐标数组绘制多边形
let renderArea = (data: any[]) => {
    // 创建要素
    const features = [
        new Feature({
            geometry: new Polygon([data])
        })
    ];
    // 创建矢量数据源
    const source = new VectorSource({
        features
    });
    // 创建样式
    const style = new Style({
        stroke: new Stroke({
            color: '#4c99f8',
            width: 3,
            lineDash: [5]
        }),
        fill: new Fill({
            color: 'rgba(255,0,0,0.91)'
        })
    });

    //创建矢量图层
    const areaLayer = new VectorLayer({
        source,
        style,
        zIndex: 100
    });
    // 添加到地图实例
    map.value.addLayer(areaLayer);
};

// 给元素加注释
let tooltipOverlay = () => {
    const tooltipOverlay = new Overlay({
        element: olPopup.value,
        positioning: 'bottom-center',
        offset: [0, 30],
        autoPan: true
    });
    map.value.addOverlay(tooltipOverlay);

    map.value.on('pointermove', (e) => {
        olPopupText.value = '';
        map.value.forEachFeatureAtPixel(e.pixel, (f: any, layer: any) => {
            if (!layer || !layer.className_) {
                return false;
            }
            olPopupText.value = '你好';

            console.log(
                'f===',
                layer.className_,
                f.getGeometry().getCoordinates()
            );

            tooltipOverlay.setPosition(f.getGeometry().getCoordinates());
        });
    });
};

// 获取当前地图区域上下左右四个点的经纬度
let calculateExtent = () => {
    let range = map.value.getView().calculateExtent(map.value.getSize());
    let state = {
        minLon: range[0],
        minLat: range[1],
        maxLon: range[2],
        maxLat: range[3],
        zoomLevel: map.value.getView().getZoom()
    };
    console.log(state, 'calculateExtent=');
};

onMounted(() => {
    initMap();
});
</script>

<style scoped lang="scss">
.container {
    width: 100%;
    height: 100%;
}
.TianDiMap {
    width: 100%;
    height: 100%;
}
</style>

